Contrôleur
==========

Un contrôleur est une instance de [CController] ou d'une classe qui en hérite.
Il est créé par l'objet application lorsque l'utilisateur en fait la demande. Quand un contrôleur
s'exécute, il effectue l'action demandée, ce qui habituellement appelle
les modèles nécessaires et affiche la vue appropriée. Une `action`, dans sa forme la plus simple, est
juste une méthode de la classe contrôleur dont le nom commence par `action`.

Un contrôleur a une action par défaut. Lorsque la requête de l'utilisateur ne spécifie pas
d'action à exécuter, l'action par défaut sera exécutée. Par défaut,
l'action par défaut est nommée `index`. Elle peut être modifiée en spécifiant la
variable d'instance publique, [CController::defaultAction].

Le code suivant définit un contrôleur `site`, une action `index` (l'action par défaut), et
une action `contact` :

~~~
[php]
class SiteController extends CController
{
	public function actionIndex()
	{
		// ...
	}

	public function actionContact()
	{
		// ...
	}
}
~~~


Route
-----

Les contrôleurs et les actions sont identifiés par des ID. Un ID de contrôleur est
au format `path/to/xyz`, ce qui correspond au fichier de classe du contrôleur
`protected/controllers/path/to/XyzController.php`, et où le jeton `xyz`
doit être remplacé par les noms réels; par exemple `post` correspond à
`protected/controllers/PostController.php`. L'ID de l'action est le nom de la méthode
d'action sans le préfixe `action`. Par exemple, si une classe de contrôleur
contient une méthode nommée `actionEdit`, l'ID de l'action correspondante serait `edit`.

Les utilisateurs nécessitent un contrôleur et une action spécifiques en termes de route.
Une route est formée par la concaténation d'un ID de contrôleur et un ID d'action, séparés
par une barre oblique. Par exemple, la route `post/edit` réfère à `PostController`
et son action `edit`. Par défaut, l'URL `http://hostname/index.php?r=post/edit`
demande le contrôleur post et l'action edit.

>Remarque : Par défaut, les itinéraires sont sensibles à la casse. Il est
>possible de faire des routes insensibles à la casse en mettant [CUrlManager::caseSensitive]
>à false dans la configuration de l'application. En cas de casse mode,
>assurez-vous de suivre la convention que les répertoires contenant les fichiers de classes de contrôleurs
>sont en minuscules, et les deux [carte contrôleur|CWebApplication::controllerMap]
>et la [carte d'action|CController::actions] ont des touches minuscules.

Une application peut contenir des [modules](/doc/guide/basics.module). La route pour
une action du contrôleur intérieur d'un module est au format `moduleID/controllerID/actionID`.
Pour plus de détails, voir la [section sur les modules](/doc/guide/basics.module).


Instanciation contrôleur
------------------------

Une instance de contrôleur est créé lorsque [CWebApplication] traite
une demande entrante. Compte tenu de l'ID du contrôleur, l'application utilise
les règles suivantes pour déterminer quelle est la classe de contrôleur et
où le fichier de classe est situé.

   - Si [CWebApplication::catchAllRequest] est spécifié, un contrôleur
sera créé sur la base de cette propriété, et l'ID du contrôleur spécifié par l'utilisateur
seront ignorés. Elle est principalement utilisée pour mettre l'application
en mode de maintenance et d'afficher une page d'avis statique.

   - Si l'ID se trouve dans [CWebApplication::controllerMap], la
configuration du contrôleur correspondant sera utilisé pour créer
l'instance du contrôleur.

   - Si l'ID est au format `path/to/xyz`, le nom de la classe contrôleur
est supposé être `XyzController` et le fichier de classe correspondante est
`protected/controllers/path/to/XyzController.php`. Par exemple, un ID de contrôleur
`admin/user` devrait être mappé à la classe contrôleur `UserController`
et le fichier de classe `protected/controllers/admin/UserController.php`.
Si le fichier de classe n'existe pas, un 404 [CHttpException] sera soulevée.

Lorsque les [modules](/doc/guide/basics.module) sont utilisés, le processus ci-dessus est
légèrement différente. En particulier, l'application vérifie si oui ou non
l'ID se réfère à un dispositif de commande à l'intérieur d'un module, et si c'est le cas,
l'instance de module est créé en premier, suivie par l'instance de contrôleur.


Action
------

Comme indiqué précédemment, une action peut être définie comme une méthode dont le nom commence
par le mot `action`. Une technique plus avancée consiste à définir une classe d'action
et de demander au contrôleur de l'instancier à la demande. Cela permet
actions à être réutilisés et introduit donc plus réutilisabilité.

Pour définir une classe nouvelle action, procédez comme suit :

~~~
[php]
class UpdateAction extends CAction
{
	public function run()
	{
		// Placer la logique de l'action ici
	}
}
~~~

Pour rendre le contrôleur au courant de cette action, nous l'emporter sur les
[actions()|CController::actions] méthode de notre classe contrôleur :

~~~
[php]
class PostController extends CController
{
	public function actions()
	{
		return array(
			'edit'=>'application.controllers.post.UpdateAction',
		);
	}
}
~~~


Dans ce qui précède, nous utilisons le chemin alias
`application.controllers.post.UpdateAction` pour spécifier que le fichier de classe d'action
est `protected/controllers/post/UpdateAction.php`.

En écrivant basés sur les classes actions, nous pouvons organiser une application de manière modulaire.
Par exemple, la structure de répertoire suivante peut être utilisée pour
organiser le code pour les contrôleurs :

~~~
protected/
	controllers/
		PostController.php
		UserController.php
		post/
			CreateAction.php
			ReadAction.php
			UpdateAction.php
		user/
			CreateAction.php
			ListAction.php
			ProfileAction.php
			UpdateAction.php
~~~

### Paramètre Action reliure

Depuis la version 1.1.4, Yii a ajouté le support pour la liaison automatique des paramètres d'action.
Autrement dit, une méthode d'action contrôleur peut définir des paramètres nommés, dont la valeur sera
automatiquement rempli à partir de `$_GET` par Yii.

Pour illustrer ce fonctionnement, supposons que nous devons écrire une action `create` pour
`PostController`. L'action requiert deux paramètres :

* `category` : un entier indiquant l'ID de catégorie en vertu de laquelle le nouveau poste
   sera créé;
* `language` : une chaîne indiquant le code de langue que le nouveau post sera dedans.

Nous pouvons finir avec le code suivant ennuyeux dans le but de récupérer les valeurs des paramètres
nécessaires de `$_GET` :

~~~
[php]
class PostController extends CController
{
	public function actionCreate()
	{
		if(isset($_GET['category']))
			$category=(int)$_GET['category'];
		else
			throw new CHttpException(404,'invalid request');

		if(isset($_GET['language']))
			$language=$_GET['language'];
		else
			$language='en';

		// ... Le code amusant commence ici ...
	}
}
~~~

Maintenant, en utilisant la fonction de paramètre action, nous pouvons accomplir notre tâche plus agréable:

~~~
[php]
class PostController extends CController
{
	public function actionCreate($category, $language='en')
	{
		$category=(int)$category;

		// ... Le code amusant commence ici ...
	}
}
~~~

Notez que nous avons ajouté deux paramètres à la méthode d'action `actionCreate`.
Les noms de ces paramètres doivent être exactement les mêmes que ceux que attendus
du `$_GET`. La paramètre `$language` prend une valeur par défaut `en`
au cas où la requête ne contient pas ce paramètre. Comme `$category` n'a pas de
valeur par défaut, si la requête ne comporte pas de paramètre `category`,
une [CHttpException](error code 400) sera automatiquement levée.

Depuis la version 1.1.5, Yii supporte également la détection du type tableau pour les paramètres de l'action.
Cela se fait par allusion au type PHP en utilisant une syntaxe comme suit:

~~~
[php]
class PostController extends CController
{
	public function actionCreate(array $categories)
	{
		// Yii veillera à ce que les $categories est un tableau
	}
}
~~~

Autrement dit, nous ajoutons le mot-clé `array` en face de `$categories` dans la déclaration
du paramètre de la méthode. Ce faisant, si `$_GET['categories']` est une chaîne simple, il sera
converti en un tableau constitué de cette chaîne.

> Remarque : Si un paramètre est déclaré sans l'allusion au type `array`, cela signifie que le paramètre
> doit être un scalaire (ie, pas un tableau). Dans ce cas, passer un paramètre de type tableau via
> `$_GET` provoquerait une exception HTTP.

Depuis la version 1.1.7, la liaison automatique des paramètres fonctionne également pour
les actions basées sur des classe. Lorsque la méthode  `run()` d'une classe d'action est définie
avec des paramètres, ceux-ci seront renseignés/initialisés avec les valeurs des paramètres de requête correspondants.
Par exemple:

~~~
[php]
class UpdateAction extends CAction
{
	public function run($id)
	{
		// $id sera renseigné/initialisé avec $_GET['id']
	}
}
~~~


Filtre
------

Un filtre est un morceau de code qui est configuré pour être exécuté avant et/ou
après l'exécution de l'action du contrôleur. Par exemple, un filtre de contrôle d'accès
peut être exécuté afin de s'assurer que l'utilisateur est authentifié avant d'exécuter
l'action demandée; Un filtre de performances peut être utilisé pour mesurer le temps
passé à l'exécution de l'action.

Une action peut avoir plusieurs filtres. Les filtres sont exécutés dans l'ordre
où ils apparaissent dans la liste des filtres. Un filtre peut empêcher l'exécution
de l'action et du reste des filtres non encore exécutés.

Un filtre peut être défini comme une méthode de la classe contrôleur. Le nom de la méthode doit
commencer par `filter`. Par exemple, une méthode nommée `filterAccessControl`
définit un filtre nommé `accessControl`. La  méthode de filtrage doit comporter
une signature précise:

~~~
[php]
public function filterAccessControl($filterChain)
{
	// Appel $filterChain->run() pour continuer l'exécution du filtre et l'action
}
~~~

où `$filterChain` est une instance de [CFilterChain] qui représente
la liste des filtres associés à l'action demandée. A l'intérieur d'une méthode de filtrage,
on peut appeler `$filterChain->run()` pour continuer à filtrer et exécuter l'action.

Un filtre peut également être une instance de [CFilter] ou de sa classe enfant.
Le code suivant définit une nouvelle classe de filtre:

~~~
[php]
class PerformanceFilter extends CFilter
{
	protected function preFilter($filterChain)
	{
		// La logique à appliquer avant que l'action soit exécutée
		return true; // false si l'action ne doit pas être exécuté
	}

	protected function postFilter($filterChain)
	{
		// La logique à appliquer après que l'action soit exécutée
	}
}
~~~

Pour appliquer des filtres à des actions, nous avons besoin de surcharger
la méthode `CController::filters()`. La méthode doit retourner un tableau
de configuration des filtres. Par exemple:

~~~
[php]
class PostController extends CController
{
	......
	public function filters()
	{
		return array(
			'postOnly + edit, create',
			array(
				'application.filters.PerformanceFilter - edit, create',
				'unit'=>'second',
			),
		);
	}
}
~~~

Le code ci-dessus spécifie deux filtres: `postOnly` et `PerformanceFilter`.
Le filtre `postOnly` est basé sur une méthode (la méthode de filtre correspondante
est définie dans [CController] déjà), tandis que le filtre `PerformanceFilter` est basé
sur un objet. L'alias de chemin `application.filters.PerformanceFilter`
spécifie que le fichier de classe du filtre est `protected/filters/PerformanceFilter`.
Nous utilisons un tableau de configurer `PerformanceFilter` de sorte qu'il peut être
utilisé pour initialiser les valeurs des propriétés de l'objet filtre. Dans cet exemple,
la propriété `unit` de `PerformanceFilter` sera initialisée à `second`.

En utilisant les opérateurs plus et moins, il est possible de spécifier pour quelles actions
le filtre doit ou ne doit pas être appliqué. Dans ce qui précède, le filtre `postOnly`
sera appliqué pour les actions `edit` et `create`, tandis que le filtre `PerformanceFilter`
sera appliqué à toutes les actions SAUF `edit` et `create`.
Si aucun des signes plus ou moins apparaît dans la configuration du filtre,
le filtre sera appliqué à toutes les actions.

<div class="revision">$Id$</div>
